package suery;

import java.awt.Component;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

import suery.syntax.SyntaxEngine;

/**
 * Swing Query Utility. It is easy to query swing component by using
 * <code>$</code> or <code>$list</code> method.</br> To use this utility, you
 * should first use <code>analyze</code> method to analyze your top level
 * container (JFrame, JDialog, JWindow and so on).</br>And then you can use
 * <code>$</code> method to query single swing component, or use
 * <code>$list</code> method to query list.
 * 
 * <p>
 * Example:
 * <pre>
 * import java.awt.BorderLayout;
 * import javax.swing.*;
 *
 * import static suery.Suery.*;// static import this and you can use $ method directly. 
 *
 * public class SueryTestFrame extends JFrame {
 *
 *     public SueryTestFrame() {                  //query by <b>SueryTestFrame</b>
 *         JTextArea area = new JTextArea(20, 20);//query by <b>SueryTestFrame/JScrollPane/JTextArea</b>
 *         this.add(new JScrollPane(area));
 * 
 *         JPanel panel = new JPanel();
 *         panel.setName("button panel");         //query by <b>#button panel</b>
 *         button = new JButton("query");
 *         panel.add(button);
 *         this.add(panel, BorderLayout.SOUTH);   //query by <b>SueryTestFrame/JPanel[South]</b>
 *
 *         this.pack();
 *         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 *         analyze(this);
 *     }
 *     private JButton button;                     //query by <b>SueryTestFrame.button</b>
 * }
 * </pre>
 * 
 * @author Jeky
 * @version 0.8b
 */
public final class Suery {

    /**
     * Analyze the top level container
     * 
     * @param container container
     */
    public static void analyze(RootPaneContainer container) {
        tree.analyze(container);
    }

    /**
     * Query component by expression and cast it to T class.
     * 
     * @param queryExp query expression
     * @param componentClass the class to be casted
     * @return component
     */
    public static <T> T $(String queryExp, Class<T> componentClass) {
        return (T) $(queryExp);
    }

    /**
     * Query component by expression.
     * 
     * @param queryExp query expression
     * @return component
     */
    public static Component $(String queryExp) {
        List<ComponentTreeNode> nodes = syntaxEngine.parse(queryExp, tree);
        return nodes.get(0).getComponent();
    }

    /**
     * Query list of components by expression and cast them to T class.
     * 
     * @param queryExp query expression
     * @param componentClass the class to be casted
     * @return list of components
     */
    public static <T> List<T> $list(String queryExp, Class<T> componentClass) {
        List<ComponentTreeNode> nodes = syntaxEngine.parse(queryExp, tree);
        List<T> componentList = new ArrayList<T>(nodes.size());
        for (int i = 0; i < nodes.size(); i++) {
            componentList.add((T) nodes.get(i).getComponent());
        }
        return componentList;
    }

    /**
     * Query list of components by expression.
     * 
     * @param queryExp query expression
     * @return list of components
     */
    public static List<Component> $list(String queryExp) {
        List<ComponentTreeNode> nodes = syntaxEngine.parse(queryExp, tree);
        List<Component> componentList = new ArrayList<Component>(nodes.size());
        for (int i = 0; i < nodes.size(); i++) {
            componentList.add(nodes.get(i).getComponent());
        }
        return componentList;
    }
    private static ComponentTree tree = new ComponentTree();
    private static SyntaxEngine syntaxEngine = new SyntaxEngine();
}
